import json
import os
import sys
import time
from typing import Dict, List, Optional
import re

class CRISPOptimizer:
    def __init__(self):
        self.optimization_history = []
        self.script_dir = os.path.dirname(os.path.abspath(__file__))            # 获取当前脚本所在目录，用于保存优化结果
        print("已成功初始化CRISP框架优化器，可以使用CRISP框架进行提示词优化")
    
    def extract_crisp_elements(self, long_text: str) -> Dict[str, str]:
        """
        从长文本中提取CRISP框架的各个元素
        参数:long_text: 用户输入的长文本提示词
        返回:包含CRISP各元素的字典
        """
        crisp_elements = {
            "context": "",   # 上下文
            "role": "",       # 角色
            "instruction": "", # 指令
            "style": "",      # 风格
            "purpose": ""      # 目的
        }
        # 1. 尝试识别角色（Role）
        role_patterns = [
            r"你是(.*?)\\.",
            r"假设你是(.*?)\\.",
            r"请以(.*?)的身份",
            r"请扮演(.*?)"
        ]
        for pattern in role_patterns:
            match = re.search(pattern, long_text)   # 利用re组件，从长文本中搜索角色模式
            if match:
                crisp_elements["role"] = match.group(1).strip()
                long_text = re.sub(pattern, "", long_text)
                break
        if not crisp_elements["role"]:  # 如果没有明确识别出角色，设置默认角色
            crisp_elements["role"] = "专业助手"
        # 2. 尝试识别目的（Purpose）
        purpose_patterns = [
            r"目的是(.*?)\\.",
            r"旨在(.*?)\\.",
            r"为了(.*?)\\.",
            r"目标是(.*?)\\."
        ]
        for pattern in purpose_patterns:
            match = re.search(pattern, long_text)
            if match:
                crisp_elements["purpose"] = match.group(1).strip()
                long_text = re.sub(pattern, "", long_text)
                break
        # 3. 尝试识别风格（Style）
        style_patterns = [
            r"风格(.*?)",
            r"以(.*?)的风格",
            r"请用(.*?)的方式",
            r"要求(.*?)的表达"
        ]
        for pattern in style_patterns:
            match = re.search(pattern, long_text)
            if match:
                crisp_elements["style"] = match.group(1).strip()
                long_text = re.sub(pattern, "", long_text)
                break
        # 如果没有明确识别出风格，设置默认风格
        if not crisp_elements["style"]:
            crisp_elements["style"] = "简洁明了"
        # 4. 提取指令（Instruction）- 通常是核心任务描述
        # 这里简化处理，假设剩余的大部分文本都是指令
        instruction_keywords = ["请", "需要", "要求", "希望", "烦请", "能否"]
        for keyword in instruction_keywords:
            idx = long_text.find(keyword)
            if idx != -1:
                instruction_part = long_text[idx:].strip()  # 从关键词开始到文本结束作为指令
                period_idx = instruction_part.find("。")    # 尝试分割上下文和指令
                if period_idx != -1 and period_idx < len(instruction_part) * 0.3:  # 如果句号在前30%的位置，可能是上下文
                    crisp_elements["context"] = instruction_part[:period_idx+1].strip()
                    crisp_elements["instruction"] = instruction_part[period_idx+1:].strip()
                else:
                    crisp_elements["instruction"] = instruction_part
                break
        if not crisp_elements["instruction"]:   # 如果没有找到明确的指令关键词，使用剩余文本作为指令
            crisp_elements["instruction"] = long_text.strip()
        return crisp_elements
    
    def generate_crisp_prompt(self, crisp_elements: Dict[str, str]) -> str:
        """
        根据CRISP元素生成结构化提示词
        参数:
            crisp_elements: 包含CRISP各元素的字典
        返回:
            结构化的CRISP提示词
        """
        # 构建CRISP结构化提示词
        crisp_prompt = []
        # 1. 添加角色（Role）
        if crisp_elements["role"]:
            crisp_prompt.append(f"角色: 你是{crisp_elements['role']}")
        # 2. 添加上下文（Context）
        if crisp_elements["context"]:
            crisp_prompt.append(f"上下文: {crisp_elements['context']}")
        # 3. 添加目的（Purpose）
        if crisp_elements["purpose"]:
            crisp_prompt.append(f"目的: {crisp_elements['purpose']}")
        # 4. 添加风格（Style）
        if crisp_elements["style"]:
            crisp_prompt.append(f"风格: 请以{crisp_elements['style']}的风格")
        # 5. 添加指令（Instruction）
        if crisp_elements["instruction"]:
            crisp_prompt.append(f"指令: {crisp_elements['instruction']}")
        # 组合所有元素为一个完整的提示词
        return "\n".join(crisp_prompt)
    
    def optimize_prompt(self, long_text: str) -> Dict[str, str]:
        """
        使用CRISP框架优化长文本提示词
        参数:
            long_text: 用户输入的长文本提示词
        返回:
            包含原始提示词、提取的CRISP元素和优化后提示词的字典
        """
        print(f"正在使用CRISP框架优化提示词: {long_text[:50]}{'...' if len(long_text) > 50 else ''}")
        crisp_elements = self.extract_crisp_elements(long_text)
        optimized_prompt = self.generate_crisp_prompt(crisp_elements)
        
        # 记录优化历史
        optimization_result = {
            "original_prompt": long_text,
            "crisp_elements": crisp_elements,
            "optimized_prompt": optimized_prompt,
            "optimization_method": "crisp_framework",
            "timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
        }
        self.optimization_history.append(optimization_result)
        return optimization_result
    
    def save_optimization_result(self, result: Dict, filename: str = None):
        """
        保存优化结果到文件
        
        参数:
            result: 优化结果字典
            filename: 保存的文件名，默认为None（自动生成）
        """
        # 如果没有提供文件名，根据提示词和时间戳生成唯一文件名
        if filename is None:
            # 获取当前时间戳，确保唯一性
            timestamp = time.strftime("%Y%m%d_%H%M%S")
            
            # 从结果中提取提示词信息
            if result and "original_prompt" in result:
                prompt_preview = result["original_prompt"][:10] if result["original_prompt"] else "unknown"
            else:
                prompt_preview = "unknown"
            
            # 替换文件名中的非法字符
            prompt_preview = ";".join(c for c in prompt_preview if c.isalnum() or c in ("_", "-", " ")).strip()
            
            # 构建文件名
            filename = f"crisp_optimization_result_{prompt_preview}_{timestamp}.json"
        
        # 如果提供的文件名不是绝对路径，则将其放在脚本所在目录下
        if not os.path.isabs(filename):
            filename = os.path.join(self.script_dir, filename)
        
        # 保存结果
        with open(filename, "w", encoding="utf-8") as f:
            json.dump(result, f, ensure_ascii=False, indent=2)
        
        print(f"CRISP框架优化结果已保存到 {filename}")
    
    def print_optimization_result(self, result: Dict):
        """
        打印优化结果
        
        参数:
            result: 优化结果字典
        """
        print("\n" + "="*60)
        print("原始提示词:")
        print(result["original_prompt"][:200] + ("..." if len(result["original_prompt"]) > 200 else ""))
        
        print("\n提取的CRISP元素:")
        for key, value in result["crisp_elements"].items():
            print(f"  {key}: {value}")
        
        print("\n优化后的提示词:")
        print(result["optimized_prompt"])
        print("="*60 + "\n")

def main():
    """主函数"""
    optimizer = CRISPOptimizer()
    
    print("欢迎使用CRISP框架提示词优化工具")
    print("此工具可以将长文本提示词转换为更精准、更有效的CRISP框架提示词。")
    
    while True:
        print("\n请选择操作:")
        print("1. 使用CRISP框架优化单个提示词")
        print("2. 退出")
        
        choice = input("请输入选择 (1/2): ")
        
        if choice == "1":
            long_text = input("请输入要优化的长文本提示词: ")
            result = optimizer.optimize_prompt(long_text)
            optimizer.print_optimization_result(result)
            
            # 询问是否保存结果
            save_choice = input("是否保存优化结果？(y/n): ").lower()
            if save_choice == "y":
                optimizer.save_optimization_result(result)
        
        elif choice == "2":
            print("感谢使用，再见！")
            break
        else:
            print("无效的选择，请重新输入。")

if __name__ == "__main__":
    main()